/**
 * mapbox地图方法
 */
import MapboxDraw from '@mapbox/mapbox-gl-draw';
import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css';
import MapboxLanguage from '@mapbox/mapbox-gl-language';
import { centroid as turfCentroid, featureCollection as turfFeatureCollection } from '@turf/turf';
import * as turf from '@turf/turf';
import axios from 'axios';
import _ from 'lodash-es';
import MapboxGL from 'mapbox-gl';
import { CompassControl } from 'mapbox-gl-controls';
import 'mapbox-gl-plugin-layer-group';
// 绘图用的插件
import 'mapbox-gl/dist/mapbox-gl.css';
import { storeToRefs } from 'pinia';
import proj4 from 'proj4';
import { useMapStore } from '@/stores';
import ON_LINE_ICON from '../../../assets/images/icon/巡护人员.png';
import { DEFAULT_MAP_STATE, layerGroupId } from './common-map-info';
import { closeMeasureArea, measureArea } from './common-map-measure-area';
import { closeMeasureLine, measureLineLength } from './common-map-measure-distance';

// * 国家 2000 投影坐标，3 度带
// eslint-disable-next-line
proj4.defs('EPSG:4546', '+proj=tmerc +lat_0=0 +lon_0=111 +k=1 +x_0=500000 +y_0=0 +ellps=GRS80 +units=m +no_defs');

const storeMap = useMapStore();

let draw = null;
let popup = null;
let updatePoint = null;
let marker = null;
let popup_point = null;
let timer = null;

// * 保存地图实例
export let map = null;

/** 更改源，同时对图层进行同步操作 */
export function TOGGLE_2D_SOURCE(source, options, _map = map) {
  if (source.type === 'raster') {
    CHANGE_RASTER_SOURCE(source, options, _map);
  } else if (source.type === 'vector') {
    CHANGE_VECTOR_SOURCE(source, options, _map);
  }
}

/** 移除数据源相关所有图层 */
export function REMOVE_SOURCE_LAYERS(sourceId, _map = map) {
  const layers = _map.getStyle().layers || [];

  for (let i = layers.length - 1; i >= 0; i--) {
    if (layers[i].source === sourceId) {
      _map.removeLayer(layers[i].id);
    }
  }
}

/** 更改栅格源 */
function CHANGE_RASTER_SOURCE(source, options, _map = map) {
  let visible = false;

  if (_map === map) {
    const { visibleLayers } = storeToRefs(storeMap);

    visible = visibleLayers.value.has(options.id);
  } else {
    visible = _map.getSource(options.id);
  }

  if (!visible) {
    _map.addSource(options.id, source);

    const layer = {
      id: `${String(options.id)}~base`,
      type: source.type,
      source: options.id,

      metadata: {
        source: options.id,
      },
    };

    if (options.group) {
      _map.addLayerToGroup(options.group, layer);
    } else {
      _map.addLayer(layer);
    }

    // 改变鼠标在图层上的光标形状
    _map.on('mousemove', layer.id, () => (_map.getCanvas().style.cursor = 'pointer'));
    _map.on('mouseleave', layer.id, () => (_map.getCanvas().style.cursor = ''));

    // 定位到图层
    if (options.bbox) {
      _map.fitBounds(options.bbox.split(','), { maxZoom: options?._zoom ?? 8 });
    }
  } else {
    REMOVE_SOURCE_LAYERS(options.id, _map);
    _map.removeSource(options.id);
  }
}

/** 更改矢量源 */
function CHANGE_VECTOR_SOURCE(source, options, _map = map) {
  let visible = false;

  if (_map === map) {
    const { visibleLayers } = storeToRefs(storeMap);

    visible = visibleLayers.value.has(options.id);
  } else {
    visible = _map.getSource(options.id);
  }

  if (!visible) {
    // * label 标签需要重新生成
    const labelSource = {
      // _id: `${String(options.id)}~label`,
      type: 'geojson',
      data: null,
    };

    const layers = [
      {
        id: `${String(options.id)}~polygon`,
        metadata: {
          source: options.id,
        },
        source: options.id,
        'source-layer': options.layerName,
        type: 'fill',
        paint: {
          'fill-color': randomColor(),
          'fill-opacity': ['case', ['boolean', ['feature-state', 'query'], false], 1, 0.6],
        },
        layout: {
          visibility: ~options.dataType.search(/polygon/i) ? 'visible' : 'none', // ! 不是相应的类型就直接隐藏掉
        },
      },
      {
        id: `${String(options.id)}~line`,
        metadata: {
          source: options.id,
        },
        source: options.id,
        'source-layer': options.layerName,
        type: 'line',
        paint: {
          'line-width': 3,
          'line-color': randomColor(),
        },
        layout: {
          visibility: ~options.dataType.search(/line|polygon/i) ? 'visible' : 'none', // ! 不是相应的类型就直接隐藏掉
        },
      },
      {
        id: `${String(options.id)}~point`,
        metadata: {
          source: options.id,
        },
        source: options.id,
        'source-layer': options.layerName,
        type: 'circle',
        paint: {
          'circle-color': 'red',
        },
        layout: {
          visibility: ~options.dataType.search(/point/i) ? 'visible' : 'none', // ! 不是相应的类型就直接隐藏掉
        },
      },
      // * 标注图层（自动计算要素集合）
      {
        id: `${String(options.id)}~label`,
        metadata: {
          source: `${String(options.id)}~label`,
        },
        source: `${String(options.id)}~label`,
        type: 'symbol',
        layout: {
          'text-size': 16,
          'text-variable-anchor': ['top', 'bottom', 'left', 'right'],
          // 'text-radial-offset': 0.5,
          'text-justify': 'auto',
        },
        paint: {
          'text-color': '#fff',
        },
      },
    ];

    _map.addSource(options.id, source);
    _map.addSource(`${String(options.id)}~label`, labelSource);

    layers.forEach((layer) => {
      // 添加图层
      // _map.addLayer(layer)
      _map.addLayerToGroup(layer);
      // 鼠标指针形状
      _map.on('mousemove', layer.id, () => (_map.getCanvas().style.cursor = 'pointer'));
      _map.on('mouseleave', layer.id, () => (_map.getCanvas().style.cursor = ''));
    });

    // * 标注图层属性
    _map.setLayoutProperty(`${String(options.id)}~label`, 'text-field', [
      'format',
      ['get', ' '],
      { 'font-scale': 0.75 },
    ]);

    // * 渲染实时更新标注位置
    _map.on(
      'render',
      layers.find((layer) => layer.layout.visibility === 'visible').id,
      updateLabelDataThrottle(`${String(options.id)}~label`),
    );

    // 定位到图层
    if (options.bbox) {
      _map.fitBounds(options.bbox.split(','), { maxZoom: options?._zoom ?? 8 });
    }
  } else {
    REMOVE_SOURCE_LAYERS(options.id, _map);
    _map.removeSource(options.id);
    REMOVE_SOURCE_LAYERS(`${String(options.id)}~label`, _map);
    _map.removeSource(`${String(options.id)}~label`);
  }
}

export function randomColor() {
  return `rgba(${110 + parseInt(Math.random() * 120)}, ${110 + parseInt(Math.random() * 120)}, ${
    110 + parseInt(Math.random() * 120)
  }, 1)`;
}

// 图层重新渲染时，生成新的标签数据
const UPDATE_LABEL_DATA =
  (sourceId, _map = map) =>
  (e) => {
    if (!e.features) return;

    const features = turfFeatureCollection(
      _.values(
        e.features.reduce((prev, feature) => {
          // * 去重，一个小班可能对应多个要素，取其中心点
          if (!prev[feature.id]) prev[feature.id] = [];

          prev[feature.id].push(feature);

          return prev;
        }, {}),
      ).map((array) => turfCentroid(turfFeatureCollection(array), array[0].properties)),
    );

    _map.getSource(sourceId).setData(features);
  };

const updateLabelDataThrottle = (sourceId) => _.throttle(UPDATE_LABEL_DATA(sourceId), 1e3);

/**
 *  初始化地图
 * @param {string} ID 容器id
 */

export function MAP_2D_INIT(ID) {
  map = new MapboxGL.Map({
    container: ID,
    style: {
      version: 8,
      glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf',
      sources: {},
      layers: [],
    },
    center: [DEFAULT_MAP_STATE.longitude, DEFAULT_MAP_STATE.latitude],
    zoom: DEFAULT_MAP_STATE.zoom,
    bearing: DEFAULT_MAP_STATE.bearing,
    pitch: DEFAULT_MAP_STATE.pitch,
    // maxBounds: [
    //   [85.10562342387936, 43.524941453518665],
    //   [90.37906092387965, 45.23054203417519],
    // ],
    // maxBounds: [
    //   [77.34028266413839, 40.61056453966779],
    //   [98.43403266413918, 47.461638792100985],
    // ],

    minZoom: 5,
    maxZoom: 16,
  });

  //解决canvas渲染不正确
  map.on('styledata', function () {
    map.resize();
  });

  draw = new MapboxDraw({
    displayControlsDefault: false,
  });

  map.addControl(draw);

  //去除mapbox的logo
  map._logoControl && map.removeControl(map._logoControl);

  // zoom调节器
  map.addControl(
    new MapboxGL.NavigationControl({ visualizePitch: true, showCompass: false, showZoom: true }),
    'bottom-right',
  );

  map.addControl(new CompassControl(), 'bottom-right');
  // 添加控件
  map.addControl(
    new MapboxGL.ScaleControl({
      maxWidth: 80,
      unit: 'metric',
    }),
    'bottom-left',
  );

  map.addControl(
    new MapboxLanguage({
      defaultLanguage: 'zh-Hans',
    }),
  );

  // * 添加图层组
  map.once('load', () => {
    // 添加所有的图层组（占位图层）
    _.map(layerGroupId, (id) => {
      map.addLayerGroup(id);
    });

    // * 地图初始化成功
    storeMap.INITIALIZE('2d');
  });

  window.map2d = map;

  return map;
}

/**
 * 获取map
 */
export const GET_MAPBOX_MAP = () => {
  return map;
};

/**
 * 切换3D
 */
export function mapTo3d(type) {
  if (type == '2d') {
    map.setProjection('globe');
    map.flyTo({
      pitch: 60,
      zoom: 12,
      bearing: 45,
      speed: 0.5,
    });
    map.setFog({
      color: 'rgba(66, 88, 106, 1.0)',
    });

    // Add some 3D terrain
    map.addSource('mapbox-dem', {
      type: 'raster-dem',
      url: 'mapbox://mapbox.terrain-rgb',
      tileSize: 512,
      maxzoom: 14,
    });
    map.setTerrain({
      source: 'mapbox-dem',
      exaggeration: 5,
    });
    window.requestAnimationFrame(frame);

    storeMap.CHANGE_MODE('3d');
  } else {
    if (map.getSource('mapbox-dem')) {
      map.setTerrain();
      map.removeSource('mapbox-dem');
    }

    map.setProjection('mercator');
    map.flyTo({
      pitch: 0,
      zoom: 9,
      bearing: 0,
      speed: 0.5,
    });

    storeMap.CHANGE_MODE('2d');
  }
}

let lastTime = 0.0;
let cycleTime = 0.0;
let night = true;

function frame(time) {
  const elapsedTime = (time - lastTime) / 1000.0;

  cycleTime += elapsedTime;

  if (cycleTime >= 50.0) {
    if (night) {
      // day fog styling
      map.setFog({
        // range: [-1, 2],
        // 'horizon-blend': 0.3,
        // color: '#d8f2ff',
        color: 'rgba(216, 242 ,255, 1.0)',
        // 'high-color': '#d8f2ff',
        // 'space-color': '#d8f2ff',
        // 'star-intensity': 0.0,
      });
    } else {
      // night  fog styling
      map.setFog({
        color: 'rgba(66, 88, 106, 1.0)',
      });
    }

    night = !night;
    cycleTime = 0.0;
  }

  lastTime = time;

  window.requestAnimationFrame(frame);
}

/**
 * 添加绘图工具
 */

export const ADD_DRAW = (option = {}) => {
  if (draw) {
    REMOVE_DRAW();
  }

  draw = new MapboxDraw({
    displayControlsDefault: false,

    ...option,
  });
  map.addControl(draw);
};

/**
 * 重置地图位置
 */
export const REST_MAP_FIT_BOUNDS = () => {
  const bbox = [84.385986328125, 43.57177734375, 86.605224609375, 45.791015625];

  // 界线
  map.fitBounds(
    [
      [bbox[0], bbox[1]],
      [bbox[2], bbox[3]],
    ],
    {
      padding: { top: 100, bottom: 100, left: 100, right: 100 },
      maxZoom: 7,
    },
  );
};

/**
 * 加载WMS
 */
export const CHANGE_CY_ONE_MAP_LAYER_WMS = (
  url,
  layerId,
  cql_filter,
  styles,
  groupId = layerGroupId.RASTER_ANNOTATION,
) => {
  let tilesUrl = '';

  if (styles == '苗木新疆团级边界') {
    tilesUrl = `${url}/wms?service=WMS&version=1.1.0&request=GetMap&layers=${layerId}&bbox={bbox-epsg-3857}&transparent=true&width=512&height=512&srs=EPSG:3857&format=image%2Fvnd.jpeg-png8&styles=${styles}`;
  } else {
    tilesUrl = `${url}/wms?service=WMS&version=1.1.0&request=GetMap&layers=${layerId}&bbox={bbox-epsg-3857}&transparent=true&width=512&height=512&srs=EPSG:3857&format=image%2Fvnd.jpeg-png8&CQL_FILTER=${cql_filter}&styles=${styles}`;
  }

  map.addSource(styles, {
    type: 'raster',
    tiles: [tilesUrl],
    tileSize: 512,
  });

  const layer = {
    id: styles,
    type: 'raster',
    source: styles,
    paint: {},
  };

  map.addLayerToGroup(groupId, layer);
};

/**
 * 条件查询
 */
export const GET_CONDITION_QUERY = async (params) => {
  const queryInfo = await axios.get(
    `https://snailmap.com.cn/geoserver/seedling/wfs?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAMES=${params.typeNames}&OUTPUTFORMAT=application/json&COUNT=10000000000000000&SRSNAME=EPSG:4326&CQL_FILTER=${params.cql_filter} `,
  );

  return queryInfo.data;
};

/**
 * 获取所有图层属性
 */
export const GeoServer_LAYER_MAP = async (ShpName) => {
  const queryInfo = await axios.get(
    'https://snailmap.com.cn/geoserver/seedling/wfs?service=wfs&version=2.0.0&request=GetFeature&outputFormat=application/json&COUNT=10000000000000000&SRSNAME=EPSG:4326&typeName=' +
      ShpName,
  );

  return queryInfo.data;
};

/**
 *点查询
 */
export const POINT_QUERY_FUN = async (layerName, lngLat, type) => {
  const queryInfo = await axios.get(
    `https://snailmap.com.cn/geoserver/seedling/wfs?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.1.0&TYPENAMES=${layerName}&OUTPUTFORMAT=application/json&COUNT=10000000000000000&SRSNAME=EPSG:4326&CQL_FILTER=TYPE='${type}' and INTERSECTS(the_geom,%20SRID=4326;POINT%20(${lngLat.lng}%20${lngLat.lat})) `,
  );
  // const mapZoom = map.getZoom();

  return queryInfo.data;
};

/**
 * 空间框选查询
 */

export const SPACE_QUERY_FUN = async (layerName, e) => {
  const queryInfo = await axios.get(
    `https://snailmap.com.cn/geoserver/seedling/wfs?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAMES=${layerName}&OUTPUTFORMAT=application/json&COUNT=10000000000000000&SRSNAME=EPSG:4326&CQL_FILTER=${`INTERSECTS(the_geom, SRID=4326;POLYGON((${String(
      _.chunk(_.flattenDeep(e.features[0].geometry.coordinates), 2)
        .map((item) => item.join(' '))
        .join(', '),
    )})))`}`,
  );

  if (queryInfo.data?.features?.length) {
    queryInfo.data?.features.map((item) => {
      const info = {
        tableLabel: [],
        table: {},
      };

      for (let propName in item.properties) {
        info.table[propName] = item.properties[propName];

        info.tableLabel.push(propName);
      }

      item.properties = info;
    });
  }

  return queryInfo.data;
};

/**
 * 给地图添加点数据(image)
 * layerId:图层id
 * values:点数据
 * layerKey:图层识别key：例如：'xx事件'
 * iconRatio:图标比例
 * image:图标
 */
export const ADD_MAP_POINTS_IMAGE = (layerId, values, layerKey, image, map, iconRatio = 1, maxZoom = 12) => {
  for (let i = 0; i < values.length; i++) {
    let img = image ?? values[i].image;

    map.loadImage(img, function (error, img) {
      if (error) throw error;

      map.addImage(layerId + String(values[i].id ?? values[i].userId), img, { pixelRatio: iconRatio });
    });

    const allPoints = [];

    allPoints.push(
      turf.point(
        [
          values[i].longitude ?? values[i]?.location?.y ?? values[i].lon,
          values[i].latitude ?? values[i]?.location?.x ?? values[i].lat,
        ],
        {
          ...values[i],
          layerKey,
        },
      ),
    );

    // 特征集合
    const collection = turf.featureCollection(allPoints);
    // 范围
    const bbox = turf.bbox(collection);

    const layers = {
      id: layerId + String(values[i].id ?? values[i].userId),
      type: 'symbol',
      source: {
        type: 'geojson',
        data: collection,
      },
      paint: {
        'text-color': 'white',
        'text-halo-color': 'rgba(0, 0, 0, 1)',
        'text-halo-blur': 3,
        'text-halo-width': 1,
      },
      layout: {
        'icon-image': layerId + String(values[i].id ?? values[i].userId),
        'text-field': values[i].samplePlotNum ?? values[i].singlePlantNum ?? values[i].username ?? values[i].typeName,
        'text-size': 14,
        'text-max-width': 24,
        'text-optional': true,
        'icon-anchor': 'bottom',
        'icon-offset': [0, -12],
      },
    };

    map.addLayerToGroup(layerId, layers);
    map.fitBounds(
      [
        [bbox[0], bbox[1]],
        [bbox[2], bbox[3]],
      ],
      {
        padding: { top: 100, bottom: 100, left: 100, right: 100 },
        maxZoom: maxZoom,
      },
    );
  }
};

// 高亮（实线）
export const High_Light_LAYER = async (layerId, values) => {
  for (let i = 0; i < values.length; i++) {
    const layer = {
      id: `${layerId}~light${i}`,
      type: 'line',
      source: {
        type: 'geojson',
        data: values[i],
      },
      layout: {},
      paint: {
        'line-color': '#FF0000',
        'line-width': 3,
      },
    };

    map.addLayerToGroup(layerId, layer);
  }
};

// 高亮（虚线）
export const High_Light_Dotted_Line_LAYER = async (layerId, values) => {
  const bbox = turf.bbox(values);

  const layer = {
    id: `${layerId}~DottedLight`,
    type: 'line',
    source: {
      type: 'geojson',
      data: values,
    },
    layout: {},
    paint: {
      'line-color': '#FF0000',
      'line-width': 3,
      // 'line-dasharray': [5, 5],
    },
  };

  map.addLayerToGroup(layerId, layer);

  map.fitBounds(
    [
      [bbox[0], bbox[1]],
      [bbox[2], bbox[3]],
    ],
    {
      padding: { top: 100, bottom: 100, left: 100, right: 100 },
      maxZoom: 13,
    },
  );
};

/**
 * 单个图标展示
 */
export const MAP_POINT_ONE = (layerId, values, layerKey, image, map, pixelRatio = 0.6, zoom = 14) => {
  let img = image;

  map.loadImage(img, function (error, img) {
    if (error) throw error;

    map.addImage(layerId + String(values.id_ ?? values.id ?? values.userId), img, { pixelRatio: pixelRatio });
  });

  const allPoints = [];

  allPoints.push(
    turf.point([values?.longitude ?? values?.location.y, values?.latitude ?? values?.location.x], {
      ...values,
      layerKey,
    }),
  );

  // 特征集合
  const collection = turf.featureCollection(allPoints);
  // 范围
  const bbox = turf.bbox(collection);

  const layers = {
    id: layerId + String(values.id_ ?? values.id ?? values.userId),
    type: 'symbol',
    source: {
      type: 'geojson',
      data: collection,
    },
    paint: {
      'text-color': 'white',
      'text-halo-color': 'rgba(0, 0, 0, 1)',
      'text-halo-blur': 3,
      'text-halo-width': 1,
    },
    layout: {
      'icon-image': layerId + String(values.id_ ?? values.id ?? values.userId),
      'text-field': values.samplePlotNum ?? values.singlePlantNum ?? values.username ?? '',
      'text-size': 14,
      'text-max-width': 24,
      'text-optional': true,
      'icon-anchor': 'bottom',
      'icon-offset': [0, -12],
    },
  };

  map.addLayerToGroup(layerId, layers);
  map.fitBounds(
    [
      [bbox[0], bbox[1]],
      [bbox[2], bbox[3]],
    ],
    {
      padding: { top: 100, bottom: 100, left: 100, right: 100 },
      maxZoom: zoom,
    },
  );
};

export const ADD_MAP_POINTS_ICON = (layerId, values, layerKey, image, map, iconRatio = 1, maxZoom = 12, layer) => {
  for (let i = 0; i < values.length; i++) {
    let img = image ?? values[i].image;

    map.loadImage(img, function (error, img) {
      if (error) throw error;

      map.addImage(layerId + String(values[i].id), img, { pixelRatio: iconRatio });
    });

    const allPoints = [];

    allPoints.push(
      turf.point(values[i].geometry.coordinates, {
        ...values[i],
        layerKey,
      }),
    );

    // 特征集合
    const collection = turf.featureCollection(allPoints);
    // 范围
    const bbox = turf.bbox(collection);

    const layers = {
      id: layerId + String(values[i].id),
      type: 'symbol',
      source: {
        type: 'geojson',
        data: collection,
      },
      paint: {
        'text-color': 'white',
        'text-halo-color': 'rgba(0, 0, 0, 1)',
        'text-halo-blur': 3,
        'text-halo-width': 1,
      },
      layout: {
        'icon-image': layerId + String(values[i].id),
        'text-field': values[i].properties['名称'] ?? values[i].properties['树种'],
        'text-size': 14,
        'text-max-width': 24,
        'text-optional': true,
        'icon-anchor': 'bottom',
        'icon-offset': [0, -12],
      },
    };

    map.addLayerToGroup(layerId, layers);
    map.fitBounds(
      [
        [bbox[0], bbox[1]],
        [bbox[2], bbox[3]],
      ],
      {
        padding: { top: 100, bottom: 100, left: 100, right: 100 },
        maxZoom: maxZoom,
      },
    );
  }

  // * 将数据源添加/删除
  storeMap.TOGGLE_LAYERS([String(layer.id)]);
};

/**
 * 弹窗popup
 */
export const MAP_POPUP = (features, elpopup) => {
  popup_point = new MapboxGL.Popup({
    anchor: 'bottom',
    // closeButton: false,
    offset: [0, -40],
  })
    .setLngLat([features[0].properties?.longitude, features[0].properties?.latitude])
    .setMaxWidth('600px') //设置弹窗最大宽度
    .setDOMContent(elpopup)
    .addTo(map);
};

/**
 * 动态轨迹
 */
export const MAP_UPDATE_REALTIME_LINE = (data, values, MAP_LINE_LAYER, MAP_POINT_LAYER_LIGHT) => {
  const coordinates = data.geometry.coordinates;

  data.geometry.coordinates = [coordinates[0]];

  const layers = {
    id: MAP_LINE_LAYER,
    type: 'line',
    source: {
      type: 'geojson',
      data: data,
    },
    paint: {
      'line-color': '#8fb7ff',
      'line-opacity': 0.75,
      'line-width': 5,
    },
  };

  map.addLayerToGroup(MAP_LINE_LAYER, layers);
  map.jumpTo({ center: coordinates[0], zoom: 14 });
  map.setPitch(30);

  let i = 0;

  marker = new MapboxGL.Marker({
    color: 'red',
    scale: 0.8,
    draggable: false,
    pitchAlignment: 'auto',
    rotationAlignment: 'auto',
  })
    .setLngLat(coordinates[0])
    .addTo(map);

  timer = setInterval(() => {
    if (i < coordinates.length) {
      data.geometry.coordinates.push(coordinates[i]);
      map.getSource(MAP_LINE_LAYER).setData(data);
      // map.panTo(coordinates[i]);
      marker.setLngLat(coordinates[i]);
      i++;
    } else {
      marker && marker.remove();
      window.clearInterval(timer);
      MAP_POINT_ONE(MAP_POINT_LAYER_LIGHT, values.endPoint, '巡护轨迹', ON_LINE_ICON, GET_MAPBOX_MAP(), 1, 18);
    }
  }, 35);
};

/**
 *
 * 闪烁的点坐标
 */
export const POINT_MARKER_ = (values, layerKey, item, MEASURE_POINT, pointID) => {
  // 动态图标
  const size = 100;
  const pulsingDot = {
    width: size,
    height: size,
    data: new Uint8Array(size * size * 4),

    onAdd: function () {
      var canvas = document.createElement('canvas');

      canvas.width = this.width;
      canvas.height = this.height;
      this.context = canvas.getContext('2d');
    },

    render: function () {
      var duration = 3000;
      var t = (performance.now() % duration) / duration;

      var radius = (size / 2) * 0.3;
      var outerRadius = (size / 2) * 0.7 * t + radius;
      var context = this.context;

      // draw outer circle
      context.clearRect(0, 0, this.width, this.height);
      context.beginPath();
      context.arc(this.width / 2, this.height / 2, outerRadius, 0, Math.PI * 250);
      context.fillStyle = `rgba(73, 133, 239, 0.51),` + (1 - t) + ')';
      context.strokeStyle = 'white';
      context.fill();

      // draw inner circle
      context.beginPath();
      context.arc(this.width / 2, this.height / 2, radius, 0, Math.PI * 2);
      context.fillStyle = `rgba(73, 133, 239, 1)`;
      context.strokeStyle = '#ffffff';
      context.lineWidth = 2 + 4 * (1 - t);
      context.fill();
      context.stroke();

      // update this image's data with data from the canvas
      this.data = context.getImageData(0, 0, this.width, this.height).data;

      // keep the map repainting
      map.triggerRepaint();

      // return `true` to let the map know that the image was updated
      return true;
    },
  };

  map.addImage(pointID, pulsingDot, { pixelRatio: 2 });

  const allPoints = [];

  allPoints.push(
    turf.point([values.longitude, values.latitude], {
      item,
      layerKey,
    }),
  );

  // 特征集合
  const collection = turf.featureCollection(allPoints);

  const layers = {
    id: MEASURE_POINT + values.id,
    type: 'symbol',
    source: {
      type: 'geojson',
      data: collection,
    },
    layout: {
      'icon-image': pointID,
    },
  };

  map.addLayerToGroup(MEASURE_POINT, layers);
};

/**
 *
 * @returns 清除弹窗、marker、定时器
 */
export const CLEAR_POPUP_MAP = () => {
  popup_point && popup_point.remove();
  marker && marker.remove();
  window.clearInterval(timer);
  marker = null;
  popup_point = null;
  timer = null;
};

/**
 *
 * 获取当前图层视口边界
 */
export const MAP_BOUNDS = () => {
  // 获取当前地图视口的边界框
  const bounds = map.getBounds();

  // 提取边界框的坐标信息
  const ne = bounds.getNorthEast(); // 获取东北角（Northeast）坐标
  const sw = bounds.getSouthWest(); // 获取西南角（Southwest）坐标

  const info = [
    [sw.lng, sw.lat], //西南角坐标
    [ne.lng, ne.lat], //东北角坐标
  ];

  return info;
};

/**
 * 移除绘图工具
 */
export const REMOVE_DRAW = () => {
  if (!draw) return;

  draw.deleteAll();

  map.removeControl(draw);
  draw = null;
};

/**
 * 移除指定图层
 * @param {string} layerId 图层id
 */
export function REMOVE_LAYER(layerId) {
  if (map.getLayer(layerId)) {
    map.removeLayer(layerId);
    map.removeSource(layerId);
  }
}

/**
 * 移除map_img
 */
export const REMOVE_MAP_IMG = (ID) => {
  if (map?.hasImage(ID)) {
    map?.removeImage(ID);
  }
};

/**
 * 移除地图
 */
export function REMOVE_2D_MAP() {
  window.map2d = null;
  map && map.remove();
  map = null;
}

/**
 * =========测量功能=========
 */

/**
 * 地图测量功能-测面
 */
export const MEASURE_AREA_V = () => {
  MEASURE_CLEAR();
  measureArea(map);
};

/**
 * 地图测量功能-测距
 */
export const MEASURE_LINE_V = () => {
  MEASURE_CLEAR();
  measureLineLength(map);
};

/**
 * 地图测量功能-坐标测量
 */

export const MEASURE_POINT = () => {
  proj4.defs('EPSG:4546', '+proj=tmerc +lat_0=0 +lon_0=111 +k=1 +x_0=500000 +y_0=0 +ellps=GRS80 +units=m +no_defs');

  updatePoint = (e) => {
    REMOVE_LAYER(layerGroupId.MEASURE_POINT);
    REMOVE_MAP_IMG('pulsing-dot');

    POINT_MARKER(e.lngLat);

    const xy = proj4('EPSG:4546', [e.lngLat.lng, e.lngLat.lat]);

    popup = new MapboxGL.Popup({ anchor: 'bottom', offset: 15 })
      .setLngLat(e.lngLat)
      .setHTML(
        `<div style="width:172px;border-radius: 13px;text-align:left;font-size:14px">
        <div style="margin-bottom:8px">X坐标：${xy[0].toFixed(5)}</div>
        <div >Y坐标:${xy[1].toFixed(5)}</div>
        </div>`,
      )
      .addTo(map);

    if (popup) {
      popup.on('close', () => {
        REMOVE_LAYER(layerGroupId.MEASURE_POINT);
      });
    }
  };

  map.off('click', updatePoint);
  map.on('click', updatePoint);
};

export const POINT_MARKER = (values) => {
  const size = 100;

  const pulsingDot = {
    width: size,
    height: size,
    data: new Uint8Array(size * size * 4),

    onAdd: function () {
      const canvas = document.createElement('canvas');

      canvas.width = this.width;
      canvas.height = this.height;
      this.context = canvas.getContext('2d');
    },

    render: function () {
      const radius = (size / 2) * 0.3;
      const context = this.context;

      context.beginPath();
      context.arc(this.width / 2, this.height / 2, radius, 0, Math.PI * 2);
      context.fillStyle = '#ffffff';
      context.strokeStyle = 'rgba(255, 100, 100, 1)';
      context.lineWidth = 10;
      context.fill();
      context.stroke();

      this.data = context.getImageData(0, 0, this.width, this.height).data;

      map.triggerRepaint();

      return true;
    },
  };

  map.addImage('pulsing-dot', pulsingDot, { pixelRatio: 2 });

  const layer = {
    id: layerGroupId.MEASURE_POINT,
    type: 'symbol',
    source: {
      type: 'geojson',
      data: {
        type: 'FeatureCollection',
        features: [
          {
            type: 'Feature',
            geometry: {
              type: 'Point',
              coordinates: [values.lng, values.lat],
            },
          },
        ],
      },
    },
    layout: {
      'icon-image': 'pulsing-dot',
    },
  };

  map.addLayerToGroup(layerGroupId.MEASURE_POINT, layer);
};

/**
 * 地图测量功能-清除
 */
export const MEASURE_CLEAR = () => {
  ADD_DRAW();

  if (popup) {
    popup.remove();
  }

  map.off('click', updatePoint);

  draw.deleteAll();
  REMOVE_LAYER(layerGroupId.MEASURE_POINT);
  REMOVE_MAP_IMG('pulsing-dot');
};

/**
 * 地图测量功能-清除
 */
export const MEASURE_CLEAR_V = () => {
  closeMeasureLine(map);
  closeMeasureArea(map);
  map.getCanvas().style.cursor = 'pointer';
};
